<?php

    declare(strict_types=1);

    namespace app\common\service;

    use Firebase\JWT\BeforeValidException;
    use Firebase\JWT\ExpiredException;
    use Firebase\JWT\JWT;
    use Firebase\JWT\Key;
    use Firebase\JWT\SignatureInvalidException;
    use InvalidArgumentException;
    use app\common\enum\RespCode;

    use TypeError;
    use UnexpectedValueException;

    /**
     * token 校验
     */
    class JwtAuthService
    {
        // 类型
        const TYPE = 'JWT';
        // 签名算法
        const ALG = 'HS256';
        // 密钥
        const KEY = 'ZXGJHZfb9EvcCfVpHo5u93BzQj3I6B7n';
        // 过期时间
        public $expire;

        public function __construct()
        {
            $this->expire = 60*60*24*30;
        }
        /**
         * 获取签名
         */
        public function sign(array $user)
        {
            $payload = [
                "iss" => "system", // JWT的签发者
                "sub" => 'user', // 面向用户
                "iat" => time(), // 签发时间
                "exp" => time() + $this->expire, // 过期时间
                "nbf" => time(), // 时间之前不处理
                "jti" => md5(uniqid(self::TYPE) . time()), // token唯一标识
                "data" => $user,
            ];
            return JWT::encode($payload, self::KEY, self::ALG);
        }
        /**
         * 验证token
         */
        public function verify(string $token)
        {
            try {
                $decoded = JWT::decode($token, new Key(self::KEY, self::ALG));
                if ($decoded->exp < time()) {
                    tips('请重新登录', RespCode::NOT_LOGIN);
                }
                return $decoded->data;
            } catch (InvalidArgumentException) {
                return false;
            } catch (UnexpectedValueException) {
                return false;
            } catch (SignatureInvalidException) {
                return false;
            } catch (BeforeValidException) {
                return false;
            } catch (ExpiredException) {
                return false;
            } catch (TypeError) {
                return false;
            }
        }
        /**
         * 刷新token
         */
        public function refresh(string $token, array $ui = [])
        {
            try {
                $res = $this->verify($token);
                $new_ui = $ui ? $ui : $res;
                return $this->sign($new_ui);
            } catch (ExpiredException $e) {
            }
        }
        /**
         * 获取token的id
         */
        public function uid()
        {
            $token = request()->header();
            if (!isset($token['authorization'])) {
                return 0;
            }
            $data = $this->verify(str_replace('Bearer ', '', $token));
            return $data ? $data['id'] : 0;
        }
    }
